/*
* PUBLIC DOMAIN PCCTS-BASED C++ GRAMMAR (cplusplus.g, stat.g, expr.g)
*
* Authors: Sumana Srinivasan, NeXT Inc.;            
sumana_srinivasan@next.com
*          Terence Parr, Parr Research Corporation; parrt@parr-research.com
*          Russell Quong, Purdue University;        quong@ecn.purdue.edu
*
* VERSION 1.1
*
* SOFTWARE RIGHTS
*
* This file is a part of the ANTLR-based C++ grammar and is free
* software.  We do not reserve any LEGAL rights to its use or
* distribution, but you may NOT claim ownership or authorship of this
* grammar or support code.  An individual or company may otherwise do
* whatever they wish with the grammar distributed herewith including the
* incorporation of the grammar or the output generated by ANTLR into
* commerical software.  You may redistribute in source or binary form
* without payment of royalties to us as long as this header remains
* in all source distributions.
*
* We encourage users to develop parsers/tools using this grammar.
* In return, we ask that credit is given to us for developing this
* grammar.  By "credit", we mean that if you incorporate our grammar or
* the generated code into one of your programs (commercial product,
* research project, or otherwise) that you acknowledge this fact in the
* documentation, research report, etc....  In addition, you should say nice
* things about us at every opportunity.
*
* As long as these guidelines are kept, we expect to continue enhancing
* this grammar.  Feel free to send us enhancements, fixes, bug reports,
* suggestions, or general words of encouragement at parrt@parr-research.com.
*
* NeXT Computer Inc.
* 900 Chesapeake Dr.
* Redwood City, CA 94555
* 12/02/1994
*
* Restructured for public consumption by Terence Parr late February, 1995.
*
* Requires PCCTS 1.32b4 or higher to get past ANTLR.
*
* DISCLAIMER: we make no guarantees that this grammar works, makes sense,
*             or can be used to do anything useful.
*/
/* 1999-2004 Version 3.0 July 2004
*	Main program of the C++ parser.
*	Based on 'main.cpp' supplied with John Lilley's C++ parser and modified
*    by David Wigg at London South Bank University
*
*	To run in DOS window enter,
*
*	>...\CPP_parser program_name.i (/a or /A)
*
*	The input file must be pre-processed if any types are declared outside the
*	 program in the #include files. Otherwise the parser fails.
*	Error/warning messages to displayed on the screen.
*/

#include <iostream>
#include <fstream>
#include <string>
#include "CPPLexer.hpp"
#include "CPPParser.hpp"
#include "ASTNode.hpp"


#ifdef MYCODE
#include "MyCode.hpp"
#endif //MYCODE

ANTLR_USING_NAMESPACE(std)
ANTLR_USING_NAMESPACE(antlr)

// The following data used by process_line_directive(char*,int) below
// I believe this data and function have to be at this level so as to
//	be available to both CPPLexer and CPPParser (and support.cpp)
int this_line = 0; // current line
 
int include_line = 0; // include file's line number
int include_last_set = 0; // where included file's line number was last set
char currentIncludedFile[128]; // path and name of current included file
bool in_user_file = false; // true if we are inside the users's source file

int principal_line = 0;		// principal file's line number
int principal_last_set = 0; // where principal file's line number was last set
char principal_file[128];	// path and name of principal file
bool in_principal_file = false; // true if we are inside the principal file

int main(int argc,char* argv[])
	{
	ASTNode *result;

	// Adapt the following if block to the requirements of your application
	if (argc < 2 || argc > 3)
		{
		cerr << "Usage:\n" << argv[0] << " filename.i (/a or /A)" << "\n";
		exit(1);
		}

	// check for input file
	FILE *input_file_ptr = fopen(argv[1], "r");
	if (input_file_ptr == NULL)
		{
		cerr << "Failed to open input file " << argv[1] << "\n";
		exit(1);
		}
	else
		// close input file
		fclose(input_file_ptr);

	char *f = argv[1];

	try {
		ifstream s(f);
		if (!s)
			{
			cerr << "Input stream could not be opened for " << f << "\n";
			exit(1);
			}

		// Create a scanner that reads from the input stream
		CPPLexer lexer(s);
		lexer.setFilename(f);


#ifdef MYCODE
		// Create subclass of parser for MYCODE code that reads from scanner
		MyCode myCode(lexer);
		myCode.setFilename(f);
		myCode.init();
		myCode.myCode_pre_processing(argc, argv);
		myCode.translation_unit();
		myCode.myCode_post_processing();
#else
		// Create a parser that reads from the scanner
		CPPParser parser(lexer);
		parser.setFilename(f);
        parser.init();
		result = parser.translation_unit();
		//result->print_tree();
		result->delete_subtree();
		delete result;
		parser.uninit();
#endif //MYCODE
		}
	catch (exception& e) 
		{
		cerr << "parser exception: " << e.what() << endl;
//		e.printStackTrace();   // so we can get stack trace		
		}
	printf("\nParse ended\n");
	return 0;
	}

// for processing #line .... lines (see note above)
void process_line_directive(const char *includedFile, const char *includedLineNo)
	{
	// See global interface variables above
	// Working variables
	static int line, result;
	static bool principal_file_set = false;
	static int x;

	// Extract included file line no.
	result = sscanf(includedLineNo, "%d \n", &line);

	// remove first " from file path+name by shifting all characters left
	for(x=1;includedFile[x]!='"';x++)
		{
		currentIncludedFile[x-1] = includedFile[x];
		}

	// Check path and name are not too long
	if(x>128)
		{
		//
		printf("Path and name of included file too long\n");
		printf("Increase length of currentIncludedFile and\n");
		printf("  principal_file to at least %d characters\n",x);
		printf("Abandon run\n");
		getchar();		    
		}

	// Replace last " from file name with null
	currentIncludedFile[x-1] = NULL;

	if (!principal_file_set)
		{
		strcpy (principal_file, currentIncludedFile);
		principal_file_set = true;
		}

	// check for main file name
	if (strcmp(principal_file, currentIncludedFile) == 0)
		{
		in_principal_file = true;
		principal_line = line;
		principal_last_set = this_line;
		strcpy(currentIncludedFile, " "); // delete include file name
		in_user_file = true; // we are processing users's .C or .CPP file
		}
	else
		// Check that this is a genuine path
		if(currentIncludedFile[1]==':')
			{
			in_principal_file = false;
			include_line = line;
			include_last_set = this_line;
			in_user_file = false; // we are processing a header file
			}
	}

